package com.ruoyi.durian.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.DurianConstant;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.DurianRedisKeysType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.durian.domain.LlCardPackage;
import com.ruoyi.durian.domain.LlCoupon;
import com.ruoyi.durian.domain.LlCouponExchange;
import com.ruoyi.durian.domain.LlCouponExchangeHistory;
import com.ruoyi.durian.mapper.LlCardPackageMapper;
import com.ruoyi.durian.mapper.LlCouponExchangeHistoryMapper;
import com.ruoyi.durian.mapper.LlCouponMapper;
import com.ruoyi.durian.service.LlCouponExchangeService;
import com.ruoyi.durian.mapper.LlCouponExchangeMapper;
import org.redisson.RedissonMultiLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author lenovo
 * @description 针对表【ll_coupon_exchange(优惠券模块-券码发布历史表)】的数据库操作Service实现
 * @createDate 2024-07-27 20:23:37
 */
@Service
public class LlCouponExchangeServiceImpl extends ServiceImpl<LlCouponExchangeMapper, LlCouponExchange>
        implements LlCouponExchangeService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private LlCouponExchangeHistoryMapper llCouponExchangeHistoryMapper;

    @Resource
    private LlCardPackageMapper llCardPackageMapper;

    @Resource
    private LlCouponMapper llCouponMapper;

    @Resource
    private LlCouponExchangeMapper llCouponExchangeMapper;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 券码兑换
     *
     * @param code 兑换码
     * @return
     */
    @Override
    @Transactional
    public AjaxResult exchange(String code) {
        Integer userId = SecurityUtils.getUserId().intValue();

        RLock redLock = redissonClient.getLock(DurianConstant.DURIAN_EXCHANGE_LOCK_KEY);
        RedissonMultiLock lock = new RedissonMultiLock(redLock);
        lock.lock(30000, TimeUnit.SECONDS);
        try {
            // 判断券码是否过期或已兑换完毕
            String num = stringRedisTemplate.opsForValue().get(DurianRedisKeysType.COUPON.getKey() + code);
            if (num == null || "0".equals(num)) {
                return AjaxResult.error("券码已失效");
            }
            // 获取剩余的过期时间（毫秒）
            Long ttlMillis = stringRedisTemplate.getExpire(DurianRedisKeysType.COUPON.getKey() + code, TimeUnit.MILLISECONDS);
            // 校验是否兑换过券码
            LambdaQueryWrapper<LlCouponExchange> qw = new LambdaQueryWrapper<>();
            qw.eq(LlCouponExchange::getCouponCode, code);
            LlCouponExchange coupon = llCouponExchangeMapper.selectOne(qw);

            LambdaQueryWrapper<LlCouponExchangeHistory> qwh = new LambdaQueryWrapper<>();
            qwh.eq(LlCouponExchangeHistory::getExchangeId, coupon.getId());
            qwh.eq(LlCouponExchangeHistory::getUserId, userId);
            LlCouponExchangeHistory selectOne = llCouponExchangeHistoryMapper.selectOne(qwh);

            if (selectOne != null) {
                return AjaxResult.error("该券码已兑换过");
            }
            // 对redis库存-1
            stringRedisTemplate.opsForValue().set(DurianRedisKeysType.COUPON.getKey() + code, String.valueOf(Integer.parseInt(num) - 1));
            // 重新设置剩余的过期时间
            if (ttlMillis > 0) {
                stringRedisTemplate.expire(DurianRedisKeysType.COUPON.getKey() + code, ttlMillis, TimeUnit.MILLISECONDS);
            }
            // 对mysql库存-1
            coupon.setRemainderNum(coupon.getRemainderNum() - 1);
            llCouponExchangeMapper.updateById(coupon);
            // 插入兑换记录
            LlCouponExchangeHistory history = new LlCouponExchangeHistory();
            history.setExchangeId(coupon.getId());
            history.setCouponId(coupon.getCouponId());
            history.setUserId(userId);
            history.setCreateTime(new Date());
            history.setUpdateTime(new Date());
            llCouponExchangeHistoryMapper.insert(history);
            // 存入用户卡包
            LlCoupon llCoupon = llCouponMapper.selectById(coupon.getCouponId());
            LlCardPackage cardPackage = new LlCardPackage();
            BeanUtils.copyBeanProp(cardPackage, llCoupon);
            cardPackage.setUseStartTime(llCoupon.getStartTime());
            cardPackage.setUseEndTime(llCoupon.getEndTime());
            cardPackage.setId(null);
            cardPackage.setStatus(1);
            cardPackage.setUseStatus(1);
            cardPackage.setCreateTime(new Date());
            cardPackage.setUpdateTime(new Date());
            cardPackage.setUserId(userId);
            cardPackage.setEndTime(llCoupon.getEndValidTime());
            cardPackage.setCouponId(llCoupon.getId());
            llCardPackageMapper.insert(cardPackage);
        } finally {
            lock.unlock();
        }
        return AjaxResult.success();
    }

    @Override
    public List<LlCouponExchange> selelctLlCouponExchange(LlCouponExchange llCouponExchange) {

        LambdaQueryWrapper<LlCouponExchange> qw = new LambdaQueryWrapper<>();
        qw.eq(LlCouponExchange::getIsDelete,0).orderByDesc(LlCouponExchange::getCreateTime);
        return list(qw);
    }
}




